package com.weimob.mcloud.wechatwork.customer.service.impl;

import com.alibaba.dubbo.config.annotation.Service;
import com.alibaba.fastjson.JSON;
import com.weimob.mcloud.mcloudratelimitercore.common.RatelimiterInfo;
import com.weimob.mcloud.mcloudratelimitercore.common.enums.BizLimitKeyEnum;
import com.weimob.mcloud.mcloudratelimitercore.common.enums.LimitKeyEnum;
import com.weimob.mcloud.mcloudratelimitercore.common.utils.LimitKeyUtils;
import com.weimob.mcloud.wechatwork.common.enums.CommonBizErrorEnum;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.CustomerGroupListReqDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.request.tag.MarkCropTagDTO;
import com.weimob.mcloud.wechatwork.core.adapter.pojo.dto.channel.response.CustomerGroupListResBO;
import com.weimob.mcloud.wechatwork.core.entity.privatesphere.PrivateSphere;
import com.weimob.mcloud.wechatwork.customer.domain.ExternalUserChangeInfo;
import com.weimob.mcloud.wechatwork.customer.domain.dto.CorpExternalUserTag;
import com.weimob.mcloud.wechatwork.customer.domain.enums.CorpExternaluserChangEventEnum;
import com.weimob.mcloud.wechatwork.customer.mq.dto.CorpChatGroupDTO;
import com.weimob.mcloud.wechatwork.customer.mq.handler.externaluser.AddCorpExternaluserHandler;
import com.weimob.mcloud.wechatwork.customer.mq.handler.externaluser.EditCorpExternaluserHandler;
import com.weimob.mcloud.wechatwork.customer.mq.handler.externaluser.HistoryCorpExternalUserSyncHandler;
import com.weimob.mcloud.wechatwork.customer.mq.handler.group.ChatGroupConverter;
import com.weimob.mcloud.wechatwork.customer.mq.handler.group.CreateGroupChatHandler;
import com.weimob.mcloud.wechatwork.customer.mq.handler.group.UpdateGroupChatHandler;
import com.weimob.mcloud.wechatwork.customer.mq.model.ChatGroupFacade;
import com.weimob.mcloud.wechatwork.customer.mq.model.RemoteChatGroupServiceProxy;
import com.weimob.mcloud.wechatwork.customer.service.ChannelTagService;
import com.weimob.mcloud.wechatwork.customer.service.RatelimiterCallBackService;
import com.weimob.mcloud.wechatwork.customer.service.user.module.dto.tag.v2.MarkTagCallbackDTO;
import com.weimob.mcloud.wechatwork.customer.third.PrivateSphereThird;
import com.weimob.soa.common.exception.SoaException;
import com.weimob.soa.common.json.JsonUtil;
import com.weimob.soa.common.response.SoaResponse;
import com.weimob.soa.common.utils.SoaUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.List;
import java.util.Objects;

/**
 * @author yong.wu
 * @Description
 * @since 2022/8/8 17:30
 */
@Slf4j
@Service
public class RatelimiterCallBackServiceImpl implements RatelimiterCallBackService {

    @Autowired
    private RedisTemplate<String, RatelimiterInfo> redisTemplate;

    @Autowired
    private ChannelTagService channelTagService;

    @Autowired
    private ArtemisService artemisService;

    @Autowired
    RemoteChatGroupServiceProxy remoteChatGroupServiceProxy;

    @Autowired
    private ChatGroupFacade chatGroupFacade;

    @Autowired
    private PrivateSphereThird privateSphereThird;

    @Autowired
    private EditCorpExternaluserHandler editCorpExternaluserHandler;

    @Autowired
    private AddCorpExternaluserHandler addCorpExternaluserHandler;

    @Autowired
    private HistoryCorpExternalUserSyncHandler historyCorpExternalUserSyncHandler;

    @Autowired
    private CreateGroupChatHandler createGroupChatHandler;

    @Autowired
    private UpdateGroupChatHandler updateGroupChatHandler;

    @Autowired
    @Qualifier("rateLimitForGroupThreadPool")
    private ThreadPoolTaskExecutor rateLimitForGroupThreadPool;

    @Override
    public SoaResponse<?, ?> apply(Long taskId) {

        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));

        if (ratelimiterInfo == null) {
            log.error("客户回调，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }

        String limitKey = ratelimiterInfo.getLimitKey();

        if (LimitKeyEnum.TAG_MARK.getKey().equals(limitKey)) {
            //客户打标签回调
            return addTagCallBack(ratelimiterInfo, taskId);

        } else if (LimitKeyEnum.SLEF_EXTERNAL_CONTACT_GET.getKey().equals(limitKey)) {

            if (StringUtils.isBlank(ratelimiterInfo.getBizLimitKey())) {

                return SoaUtil.ok("客户限流回调服务没有对应的处理逻辑");
            }

            if (BizLimitKeyEnum.NOW_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(ratelimiterInfo.getBizLimitKey())) {

                return addExternalUserCallBack(taskId);

            } else if (BizLimitKeyEnum.EDIT_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(ratelimiterInfo.getBizLimitKey())) {

                return editExternalUserCallBack(taskId);

            } else if (BizLimitKeyEnum.HISTORY_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(ratelimiterInfo.getBizLimitKey())) {

                return historySyncExternalUserCallBack(taskId);
            }
        }
        log.warn("客户限流回调服务没有对应的处理逻辑 taskId={},RatelimiterInfo={}", taskId, ratelimiterInfo);
        return SoaUtil.ok("客户限流回调服务没有对应的处理逻辑");
    }

    public SoaResponse<?, ?> addTagCallBack(RatelimiterInfo ratelimiterInfo, Long taskId) {
        MarkTagCallbackDTO markTagCallbackDTO = JsonUtil.transferToObj(ratelimiterInfo.getJson(), MarkTagCallbackDTO.class);
        CorpExternalUserTag corpTagGroupDTO = new CorpExternalUserTag();
        corpTagGroupDTO.setUserId(markTagCallbackDTO.getUserId());
        corpTagGroupDTO.setExternalUserId(markTagCallbackDTO.getExternalUserId());
        corpTagGroupDTO.setAddTag(markTagCallbackDTO.getAddTag());
        corpTagGroupDTO.setRemoveTag(markTagCallbackDTO.getRemoveTag());
        corpTagGroupDTO.setCorpId(markTagCallbackDTO.getCorpId());
        corpTagGroupDTO.setBosId(markTagCallbackDTO.getBosId());
        SoaResponse<MarkCropTagDTO, Void> response = channelTagService.addUserTagV2(corpTagGroupDTO, taskId, markTagCallbackDTO.getType());
        try {
            if (SoaUtil.isSucc(response)) {
                Boolean delete = redisTemplate.delete(String.valueOf(taskId));
                log.info("重试成功，删除taskId={} result={}", taskId, delete);
            }
        } catch (Exception e) {
            log.error("delete taskId error taskId={}", taskId);
        }

        return response;
    }

    /**
     * 历史同步-添加外部联系人消息调用腾讯限频-回调
     *
     * @param taskId
     * @return
     */
    @Override
    public SoaResponse<?, ?> historySyncExternalUserCallBack(Long taskId) {
        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));
        if (ratelimiterInfo == null) {
            log.error("历史客户同步回调，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }
        //限频业务主key
        String limitKey = ratelimiterInfo.getLimitKey();
        //限频业务子key
        String bizLimitKey = ratelimiterInfo.getBizLimitKey();
        if (LimitKeyEnum.SLEF_EXTERNAL_CONTACT_GET.getKey().equals(limitKey)
                && BizLimitKeyEnum.HISTORY_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(bizLimitKey)) {

            //获取redis中限频实体
            ExternalUserChangeInfo userChangeInfo = JSON.parseObject(ratelimiterInfo.getJson(), ExternalUserChangeInfo.class);
            //设置taskId保证不会再次生成限频任务
            userChangeInfo.setTaskId(taskId);
            SoaResponse<?, ?> callSuccess = historyCorpExternalUserSyncHandler.handleCorpExternalUser(userChangeInfo);
            if (SoaUtil.isSucc(callSuccess)) {
                return SoaUtil.ok("历史客户同步限流处理成功");
            } else {
                if (Objects.nonNull(callSuccess)
                        && (CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode().equals(callSuccess.getReturnCode())
                        || CommonBizErrorEnum.WECHAT_WORK_CONVERT_ID_LIMIT.getCode().equals(callSuccess.getReturnCode()))
                ) {
                    return SoaUtil.error(CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode(), "历史客户同步限流回调被限频", null);
                }
            }
        }
        return SoaUtil.ok("历史客户同步限流回调服务没有对应的处理逻辑");
    }


    /**
     * 添加外部联系人消息调用腾讯限频-回调
     *
     * @param taskId
     * @return
     */
    @Override
    public SoaResponse<?, ?> addExternalUserCallBack(Long taskId) {
        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));
        if (ratelimiterInfo == null) {
            log.error("客户回调，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }
        //限频业务主key
        String limitKey = ratelimiterInfo.getLimitKey();
        //限频业务子key
        String bizLimitKey = ratelimiterInfo.getBizLimitKey();
        if (LimitKeyEnum.SLEF_EXTERNAL_CONTACT_GET.getKey().equals(limitKey)
                && (BizLimitKeyEnum.NOW_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(bizLimitKey))) {

            //获取redis中限频实体
            ExternalUserChangeInfo userChangeInfo = JSON.parseObject(ratelimiterInfo.getJson(), ExternalUserChangeInfo.class);
            //设置taskId保证不会再次生成限频任务
            userChangeInfo.setTaskId(taskId);
            SoaResponse<?, ?> callSuccess = addCorpExternaluserHandler.handleCorpExternalUser(userChangeInfo);
            if (SoaUtil.isSucc(callSuccess)) {
                return SoaUtil.ok("添加好友消息限流处理成功");
            } else {
                if (Objects.nonNull(callSuccess)
                        && (CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode().equals(callSuccess.getReturnCode())
                        || CommonBizErrorEnum.WECHAT_WORK_CONVERT_ID_LIMIT.getCode().equals(callSuccess.getReturnCode()))
                ) {
                    return SoaUtil.error(CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode(), "添加好友消息限流回调被限频", null);
                }
            }
        }
        return SoaUtil.ok("添加好友消息限流回调服务没有对应的处理逻辑");
    }

    /**
     * 添加外部联系人消息调用腾讯限频-回调
     *
     * @param taskId
     * @return
     */
    @Override
    public SoaResponse<?, ?> editExternalUserCallBack(Long taskId) {
        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));
        if (ratelimiterInfo == null) {
            log.error("编辑客户回调，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }
        String limitKey = ratelimiterInfo.getLimitKey();
        String bizLimitKey = ratelimiterInfo.getBizLimitKey();

        if (LimitKeyEnum.SLEF_EXTERNAL_CONTACT_GET.getKey().equals(limitKey)
                && BizLimitKeyEnum.EDIT_ADD_EXTERNAL_CONTACT_NOW.getKey().equals(bizLimitKey)) {
            //获取redis中限频实体
            ExternalUserChangeInfo userChangeInfo = JSON.parseObject(ratelimiterInfo.getJson(), ExternalUserChangeInfo.class);
            //设置taskId保证不会再次生成限频任务
            userChangeInfo.setTaskId(taskId);
            SoaResponse<?, ?> callSuccess = editCorpExternaluserHandler.handleCorpExternalUser(userChangeInfo);
            if (SoaUtil.isSucc(callSuccess)) {
                return SoaUtil.ok("编辑好友消息限流处理成功");
            } else {
                if (Objects.nonNull(callSuccess)
                        && (CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode().equals(callSuccess.getReturnCode())
                        || CommonBizErrorEnum.WECHAT_WORK_CONVERT_ID_LIMIT.getCode().equals(callSuccess.getReturnCode()))
                ) {
                    return SoaUtil.error(CommonBizErrorEnum.WECHAT_WORK_LIMIT.getCode(), "编辑好友消息限流回调被限频", null);
                }
            }
        }
        return SoaUtil.ok("编辑好友消息限流回调没对应处理逻辑");
    }

    /**
     * 查客户群详情-调用腾讯限频-回调
     *
     * @param taskId
     * @return
     */
    @Override
    public SoaResponse<?, ?> queryCustomerGroupCallBack(Long taskId) {
        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));
        if (ratelimiterInfo == null) {
            log.error("查客户群详情，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }
        String limitKey = ratelimiterInfo.getLimitKey();
        if (LimitKeyEnum.CUSTOMER_GROUP_GET.getKey().equals(limitKey)) {
            // 具体回调处理
            CorpChatGroupDTO dto = JSON.parseObject(ratelimiterInfo.getJson(), CorpChatGroupDTO.class);
            ExternalUserChangeInfo userChangeInfo = new ExternalUserChangeInfo();
            ChatGroupConverter.convert2ExternalUserChangeInfo(userChangeInfo, dto);
            SoaResponse<?, ?> soaResponse;
            // 历史数据走创建逻辑 实时数据根据ChangeType判断是创建还是更新
            if (Boolean.TRUE.equals(dto.getIsInitGroup())) {
                soaResponse = createGroupChatHandler.handleCorpExternalUser(userChangeInfo);
            } else {
                if (CorpExternaluserChangEventEnum.CREATE_CHAT_GROUP.getChangeType().equals(dto.getChangeType())) {
                    soaResponse = createGroupChatHandler.handleCorpExternalUser(userChangeInfo);
                } else {
                    soaResponse = updateGroupChatHandler.handleCorpExternalUser(userChangeInfo);
                }
            }
            return soaResponse;
        } else {
            return SoaUtil.error(CommonBizErrorEnum.ILLEGAL_ARGUMENTS.getCode(), "非查询客户群详情限频", null);
        }
    }

    /**
     * 查询客户群列表-调用腾讯限频-回调
     *
     * @param taskId
     * @return
     */
    @Override
    public SoaResponse<?, ?> queryCustomerGroupListCallBack(Long taskId) {
        RatelimiterInfo ratelimiterInfo = redisTemplate.opsForValue().get(LimitKeyUtils.buildRedisKey(taskId));
        if (ratelimiterInfo == null) {
            log.error("查询客户群列表，已找不到对应的限流上下文 taskId={}", taskId);
            return SoaUtil.error(CommonBizErrorEnum.NULL_ARGUMENT.getCode(), "限流回调上下文丢失", null);
        }
        String limitKey = ratelimiterInfo.getLimitKey();
        if (LimitKeyEnum.CUSTOMER_GROUP_LIST_GET.getKey().equals(limitKey)) {
            CustomerGroupListReqDTO reqDTO = JSON.parseObject(ratelimiterInfo.getJson(), CustomerGroupListReqDTO.class);
            // 查询私域信息
            PrivateSphere privateSphere = privateSphereThird.fetch(reqDTO.getCorpId());
            // 查询客户群列表
            List<CustomerGroupListResBO.GroupChat> groupChatList;
            try {
                groupChatList = remoteChatGroupServiceProxy.getAllCorpGroupChatList(privateSphere, reqDTO.getOwnerList());
            } catch (SoaException e) {
                return SoaUtil.error(e.getErrcode(), e.getErrmsg(), null);
            }
            // 同步客户群 异步处理
            rateLimitForGroupThreadPool.execute(() ->
                    chatGroupFacade.syncData(privateSphere, groupChatList)
            );
            return SoaUtil.ok("查询客户群列表限流处理成功");
        } else {
            return SoaUtil.error(CommonBizErrorEnum.ILLEGAL_ARGUMENTS.getCode(), "非查询客户群列表限频", null);
        }
    }


}
